package org.streets.commons.expression;

/**
 * 词法分析器
 * 
 * @author dzb
 */
public class Lexer {
	public final static String ALL_SPECIAL_CHAR = "~`!@#$%^&*()-=_+{};':\"./<>?\\|"; //remove , [ ]
	public final static String ALL_STRING_QUOTE = "'\"";// 优先于ALL_SPECIAL_CHAR处理，故ALL_SPECIAL_CHAR可不必除去ALL_STRING_QUOTE

	private StringBuffer s;
	private int i;
	private int e;
	private String specialChar;// 特殊符号，遇到则将分词。
	private String quotes = ALL_STRING_QUOTE;// 字符窜标识

	public Lexer(String ss) {
		this(ss, ALL_SPECIAL_CHAR);
	}

	public Lexer(String ss, String specialChar) {
		this.specialChar = specialChar;
		s = new StringBuffer(ss.replaceAll("\\r", ""));
		i = 0;
		e = s.length() - 1;
	}

	public void setStringQuote(String chs) {
		quotes = chs;
	}

	public String getStringQuote() {
		return quotes;
	}

	public void setSpecialChar(String specialChar) {
		this.specialChar = specialChar;
	}

	public String getSpecialChar() {
		return specialChar;
	}

	public boolean isSpecialChar(char ch) {
		return specialChar.indexOf(ch) != -1;
	}

	public void addSpecialChar(char ch) {
		if (specialChar.indexOf(ch) == -1) {
			specialChar += ch;
		}
	}

	public void addSpecialChar(String chs) {
		char[] chss = chs.toCharArray();
		char ch;
		for (int i = 0, n = chss.length; i < n; i++) {
			ch = chss[i];
			if (specialChar.indexOf(ch) == -1) {
				specialChar += ch;
			}
		}
	}

	public void delSpecialChar(String chs) {
		for (int i = 0, n = chs.length(); i < n; i++) {
			delSpecialChar(chs.charAt(i));
		}
	}

	public boolean delSpecialChar(char ch) {
		StringBuffer s = new StringBuffer();
		for (int i = 0, n = specialChar.length(); i < n; i++) {
			if (specialChar.charAt(i) != ch) {
				s.append(specialChar.charAt(i));
			}
		}
		boolean deleted = specialChar.length() > s.length();
		if (deleted) {
			specialChar = s.toString();
		}
		return deleted;
	}

	public void reset() {
		i = 0;
	}

	public boolean eof() {
		return i > e;
	}

	public int pos() {
		return i;
	}

	public char next() {
		return s.charAt(i++);
	}

	public void back() {
		i--;
	}

	private String spaceToken() {
		int from = pos();
		int len = 0;
		char ch;
		while (!eof()) {
			ch = next();
			switch (ch) {
			case ' ':
			case '\t':
			case '\r':
			case '\n':
				len++;
				continue;
			default:
				back();
				return s.substring(from, from + len);
			}
		}
		return s.substring(from, from + len);
	}

	public String nextToken() {
		boolean inQuote = false;
		// 匹配的quote char，初始化值设置为非可能的quote。
		char quote = '\0';
		int from = pos();
		int len = 0;

		char ch;
		while (!eof()) {
			ch = next();
			if (quotes.indexOf(ch) != -1) {
				if (len == 0) {
					quote = ch;
					inQuote = true;
					len++;
					continue;
				} else if (inQuote) {
					len++;
					if (quote == ch) {
						inQuote = false;
						return s.substring(from, from + len);
					} else {
						continue;
					}
				} else {
					// throw new
					// ParseException("引号不匹配\n"+s.substring(0,pos())+"(错误在这里)");
					// 可能是英文的' "号，这里作文本text处理
					len++;
					continue;
				}
			} else if (specialChar.indexOf(ch) != -1) {
				if (inQuote) {
					len++;
					continue;
				} else {
					if (len == 0) {
						return String.valueOf(ch);
					} else {
						back();
						return s.substring(from, from + len);
					}
				}
			} else {
				switch (ch) {
				case ' ':
				case '\t':
				case '\r':
				case '\n': {
					if (inQuote) {
						len++;
						continue;
					} else {
						back();
						if (len == 0) {
							return spaceToken();
						} else {
							return s.substring(from, from + len);
						}
					}
				}
				default: {

					len++;
					continue;
				}
				}
			}
		}
		return s.substring(from, from + len);
	}
}
